營利是幫助專案可以長久運行的方法之一,本篇介紹以 Python 搭配 Django 進行 LINE PAY API (V3) 串接的寫法。
channel_id = settings.LINE_PAY_CLIENT_ID
channel_secret = settings.LINE_PAY_SECRET
base_url = settings.LINE_PAY_URL
LINE_PAY_URL指的是 LINE 所提供的測試環境或是正式環境,測試環境為:https://sandbox-api-pay.line.me;正式環境:https://api-pay.line.me
Request API
/v3/payments/request
Confirm API
/v3/payments/{transaction_id}/confirm
雖然 Request API 的結果會導向付款成功或失敗的頁面,可以初步根據跳轉判斷頁面是否成功,但仍然要使用 Confirm API 做再度確認。
了解完兩支主要 API 之後就直接進入實作環節:
需要先定義一個函式 generate_headers,含有許多請求的 Headers,目的是做發送時的加密處理,body_json 稍後會使用到這個變數,url 指的是 Request API (/v3/payments/request)或 Confirm API (/v3/payments/{transaction_id}/confirm) 網址,特別注意 url 參數不包含 https://api-pay.line.me:
import uuid
import base64
import hmac
import hashlib
import json
from django.utils import timezone, dateformat
# API Authentication
# views.py
def generate_headers(body_json, channel_secret, url):
    nonce = str(uuid.uuid4())
    string_to_sign = f"{channel_secret}{url}{body_json}{nonce}"
    binary_message = string_to_sign.encode()
    binary_secret_key = channel_secret.encode()
    hash = hmac.new(binary_secret_key, binary_message, hashlib.sha256)
    signature = base64.b64encode(hash.digest()).decode()
    return {
        "Content-Type": "application/json",
        "X-LINE-ChannelId": channel_id,
        "X-LINE-Authorization-Nonce": nonce,
        "X-LINE-Authorization": signature,
    }
範例中,消費者購買一款單價 30 元卡比巴拉鑰匙圈商品,共計一件,其中有幾個參數需要注意:
products_quantity
products_price
order_id
confirmUrl
cancelUrl
class RequestView(APIView):
    def get(self, request):
        url = "/v3/payments/request"
        request_url = f"{base_url}{url}"
        products_quantity = 1 # 購買的商品數量
        products_price = 30 # 購買單價
        order_id = f"{dateformat.format(timezone.now()+ timezone.timedelta(hours=8),'YmdHis')}" # 訂單編號
        body = {
            "amount": products_price * products_quantity, #總額
            "currency": "TWD",
            "orderId": order_id,
            "packages": [
                {
                    "id": "kapybara", # 系列名或分店名,像卡比巴拉周邊/臺中分鋪
                    "amount": products_price * products_quantity,
                    "products": [
                        {
                            "id": "keychain", # 商品內部名,像是卡比巴拉的鑰匙圈
                            "name": "卡比巴拉-鑰匙圈", # 呈現給消費者看的商品名
                            "imageUrl": "https://sticker.png", # 商品圖片
                            "quantity": products_quantity, # 商品數量
                            "price": products_price, # 商品單價
                        },
                    ],
                },
            ],
            "options": {
                "display": {"locale": "zh_TW"}
            },
            "redirectUrls": {
                # 付款成功要跳轉的網頁
                "confirmUrl": f"https://example.com.tw/line-pay/confirm/",
                # 付款失敗要跳轉的網頁
                "cancelUrl": f"https://example.com.tw/line-pay/cancel/",
            },
        }
        # Convert body to JSON string
        body_json = json.dumps(body)
        
        # 呼叫剛剛所定義的 API Authentication generate_headers 函式
        headers = generate_headers(body_json, channel_secret, url)
        response = requests.post(request_url, headers=headers, data=body_json)
        data = response.json()
        if data["returnCode"] == "0000": # 成功的代碼是 0000
            return Response({"paymenturl": data["info"]["paymentUrl"]}, status=200)
        else:
            return Response(
                {"detail": f"request to LINE failed: {data['returnCode']}"},
                status=500,
            )
發送成功 ("returnCode" == "0000" )的話會回傳 paymentUrl 憑著這個網址,將使用者導到 LINE PAY 付款頁面了!
{
  "paymenturl": {
    "web": "https://sandbox-web-pay.line.me/web/payment/wait?transactionReserveId=WjdeWQeqwqweqwYWlhqweqweA0QUqweqweV3I5MkJaeDV4c2JtTUpuSQ&locale=zh-TW_LP",
    "app": "line://pay/payment/WjdySEWQEqweqwe0QUFKqwetqweqweJaeDV4c2JtTUpuSQ"
  }
}
付款頁面:
當消費者進入 paymenturl 付款頁面之後若付款成功/失敗,則會根據在 Request API 所填寫的 confirmUrl 與 cancelUrl 網址跳轉至對應的頁面。
confirmUrl 頁面中可以顯示確認付款中的提醒文字,並同時呼叫 Confirm API 進行確認。 
cancelUrl 頁面中能顯示付款失敗,並在數秒過後重新跳轉回結帳頁面。 
下篇會介紹 Confirm API 實作。
在這篇文章中,我們學會了: